﻿using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;

namespace Xms.Abp.Features;

public abstract class FeaturesBase: IFeatures
{
    [FeatureIgnore]
    public IAbpLazyServiceProvider LazyServiceProvider { get; set; }

    protected TService LazyInject<TService>()
    {
        return LazyServiceProvider.LazyGetRequiredService<TService>();
    }

    protected string ProviderName
    {
        get
        {
            return GetType().GetCustomAttribute<FeaturesDefinitionAttribute>().ProviderName;
        }
    }

    protected string GetValue([CallerMemberName] string name = null, string customName = null)
    {
        return AsyncHelper.RunSync(async () => await GetValueAsync(name, customName));
    }

    protected Task<string> GetValueAsync([CallerMemberName] string name = null, string customName = null)
    {
        var properties = FeaturesHelper.GetFeatureProperties(GetType());
        if (!string.IsNullOrEmpty(name) && string.IsNullOrWhiteSpace(customName) && properties.ContainsKey(name))
        {
            customName = properties[name].GetCustomAttribute<FeatureValueAttribute>()?.CustomName ?? customName;
        }
        var featureName = FeaturesHelper.GetFeatureName(GetType(), customName ?? name);
        return LazyServiceProvider
            .LazyGetRequiredService<IXmsFeaturesStore>()
            .GetOrNullAsync(featureName, ProviderName, LazyServiceProvider
                .LazyGetRequiredService<IFeaturesProviderKeyGetter>()
                .Get(ProviderName));
    }

    protected TResult GetValue<TResult>([CallerMemberName] string name = null, string customName = null) where TResult : struct
    {
        var settingValue = GetValue(name, customName);

        return settingValue?.To<TResult>() ?? default;
    }
}
